#include <string.h>
#include <iostream>
using std::cout;
using std::endl;
using std::ostream;

class CowString{
    class CharProxy
    {
    public:
        //str1[0]得到CharProxy对象
        //str1.operator[](0);
        //返回值是临时对象CharProxy(str1,0)的副本
        //根据构造函数可知
        //_self绑定到了str1
        //_idx保存了下标0
        CharProxy(CowString & self,size_t idx)
        : _self(self)
        , _idx(idx)
        {}

        //str1[0] = str3[2] = 'X';
        char operator=(char ch);

        char operator=(const CharProxy & rhs){
            _self._pstr[_idx] = rhs._self._pstr[rhs._idx];
            return _self._pstr[_idx];
        }

        operator char(){
            return _self._pstr[_idx];
        }
        
        /* friend */ 
        /* ostream & operator<<(ostream & os,const CharProxy & rhs); */
    private:
        CowString & _self;
        size_t _idx;
    };
public:
    CowString();
    CowString(const char * pstr);
    ~CowString();
    CowString(const CowString & rhs);
    CowString & operator=(const CowString & rhs);

    //str1[0]创建出CharProxy对象
    CharProxy operator[](size_t idx);

    size_t size() const{
        return strlen(_pstr);
    }

    const char * c_str() const{
        return _pstr;
    }

    int use_count() const{
        return *(int*)(_pstr - kRefcountLength);
    }

    friend
    ostream & operator<<(ostream & os,const CowString & rhs);

    /* friend */
    /* ostream & operator<<(ostream & os,const CharProxy & rhs); */
private:
    char * malloc(const char * pstr = nullptr){
        if(pstr){
            return new char[strlen(pstr) + 1 + kRefcountLength]() + kRefcountLength;
        }else{
            return new char[1 + kRefcountLength]() + kRefcountLength;
        }
    }

    void release(){
        decreaseRefcount();
        if(use_count() == 0){
            delete [] (_pstr - kRefcountLength);
            cout << ">> delete heap" << endl;
        }
        _pstr = nullptr;
    }


    void initRefcount(){
        *(int*)(_pstr - kRefcountLength) = 1;
    }

    void increaseRefcount(){
        ++*(int*)(_pstr - kRefcountLength);
    }
    void decreaseRefcount(){
        --*(int*)(_pstr - kRefcountLength);
    }

    static const int kRefcountLength = 4;
    char * _pstr;
};

ostream & operator<<(ostream & os,const CowString & rhs){
    os << rhs._pstr;
    return os;
}

CowString::CowString()
: _pstr(malloc())
{
    cout << "CowString()" << endl;
    initRefcount();
}

CowString::CowString(const char * pstr)
: _pstr(malloc(pstr))
{
    cout << "CowString(const char *)" << endl;
    strcpy(_pstr,pstr);
    initRefcount();
}

CowString::~CowString(){
    cout << "~CowString()" << endl;
    release();
}

CowString::CowString(const CowString & rhs)
: _pstr(rhs._pstr)
{
    cout << "CowString拷贝构造" << endl;
    increaseRefcount();
}

CowString & CowString::operator=(const CowString & rhs){
    if(this != &rhs){//自赋值的判断
        release();//尝试回收原本的空间
        _pstr = rhs._pstr;//浅拷贝
        increaseRefcount();//新空间的引用计数+1
    }
    return *this;
}

#if 0
char & CowString::operator[](size_t idx){
    if(idx < size()){
        return _pstr[idx];
    }else{
        cout << "out of range" << endl;
        static char nullchar = '\0';
        return nullchar;
    }
}
#endif

#if 0
char & CowString::operator[](size_t idx){
    if(idx < size()){
        if(use_count() > 1){
            //原本空间的引用计数-1
            decreaseRefcount();
            //深拷贝
            char * temp = malloc(_pstr);
            strcpy(temp,_pstr);
            //修改指向
            _pstr = temp;
            //初始化新空间的引用计数
            initRefcount();
        }
        return _pstr[idx];
    }else{
        cout << "out of range" << endl;
        static char nullchar = '\0';
        return nullchar;
    }
}
#endif

//str1[0]
//创建CharProxy对象能够提供的材料只有CowString对象和下标
CowString::CharProxy CowString::operator[](size_t idx){
    return CharProxy(*this,idx);
}


char CowString::CharProxy::operator=(char ch){
    if(_idx < _self.size()){
        if(_self.use_count() > 1){
            //原本空间的引用计数-1
            _self.decreaseRefcount();
            //深拷贝
            char * temp = _self.malloc(_self._pstr);
            strcpy(temp,_self._pstr);
            //修改指向
            _self._pstr = temp;
            //初始化新空间的引用计数
            _self.initRefcount();
        }
        //完成赋值操作
        //通过CharProxy类对象的数据成员的操作
        //改变了创建出这个CharProxy对象的CowString对象的内容
        _self._pstr[_idx] = ch;
        return _self._pstr[_idx];
    }else{
        cout << "out of range" << endl;
        static char nullchar = '\0';
        return nullchar;
    }
}

/* //这个函数需要访问内部类的私有成员，所以要声明为内部类的友元函数 */
/* //同时要访问外部类的私有成员类型CharProxy，所以还要声明为外部类的友元函数 */
/* ostream & operator<<(ostream & os,const CowString::CharProxy & rhs){ */
/*     if(rhs._idx < rhs._self.size()){ */
/*         os << rhs._self._pstr[rhs._idx]; */
/*     }else{ */
/*         os << "out of range"; */
/*     } */
/*     return os; */
/* } */

void test0(){
    CowString str1("world");
    CowString str2 = str1;
    cout << str1[0] << endl;
    /* str1[0] = 'W'; */
    cout << str1 << endl;
    cout << str2 << endl;
    cout << "str1.use_count:" << str1.use_count() << endl;
    cout << "str2.use_count:" << str2.use_count() << endl;

    cout << endl;
    CowString str3("hello");
    CowString str4(str3);
    str3[0] = str1[1] = 'X';
    cout << str1 << endl;
    cout << str2 << endl;
    cout << str3 << endl;
    cout << str4 << endl;
    cout << "str1.use_count:" << str1.use_count() << endl;
    cout << "str2.use_count:" << str2.use_count() << endl;
    cout << "str3.use_count:" << str3.use_count() << endl;
    cout << "str4.use_count:" << str4.use_count() << endl;
}

void test1(){
    //有待完善
    CowString str1("hello");
    CowString str2("world");
    str1[0] = str2[1];
    cout << str1 << endl;
    cout << str2 << endl;
}

void test2(){
    CowString str1("hello");
    char ch = 'X';
    //用类型转换函数
    ch = str1[0];
    cout << ch << endl;
}


int main(void){
    test0();
    return 0;
}
